// Package parser: 语法分析器
package parser

import (
	"fmt"
	"strconv"
	"z-lang/ast"
	"z-lang/lexer"
	"z-lang/token"
)

const (
	_              int = iota
	LOWEST             // 运算符优先级, 从低到高
	BitOperation       // 位运算
	EQUALS             // ==
	LessGreater        // > or <
	SUM                // +
	PRODUCT            // *
	PREFIX             // -X or !X
	CALL               // myFunction(X) 函数调用
	INDEX              // 索引运算符 arr[X]
	ASSIGN             // 赋值符号 arr[X] = X
	LogicOperation     // 逻辑运算符 && ||
)

// precedences 优先级表,将词法单元类型与其优先级相关联
var precedences = map[token.TokenType]int{
	token.OR:      BitOperation,
	token.AND:     BitOperation,
	token.NOT:     BitOperation,
	token.XOR:     BitOperation,
	token.LSHIFT:  BitOperation,
	token.RSHIFT:  BitOperation,
	token.URSHIFT: BitOperation,

	token.EQ:       EQUALS,
	token.NOT_EQ:   EQUALS,
	token.LT:       LessGreater,
	token.GT:       LessGreater,
	token.PLUS:     SUM,
	token.MINUS:    SUM,
	token.SLASH:    PRODUCT,
	token.ASTERISK: PRODUCT,
	token.LPAREN:   CALL,
	token.LBRACKET: INDEX,
	token.ASSIGN:   ASSIGN,

	token.LOGIC_AND: LogicOperation,
	token.LOGIC_OR:  LogicOperation,
}

// 解析函数 (普拉特语法分析器 - 表达式解析函数与词法单元类型关联，每当遇到某个词法单元类型时(一般是以运算符做为分隔)，
//
//	调用相关联的表达式解析函数来解析对应的表达式，最后返回生成的AST节点。每个词法单元类型最多可以关联两个解析函数
//	这取决于词法单元是在前缀位置还是中缀位置)
type (
	// prefixParseFn 表达式(运算符)前缀解析函数 - 返回一个 ast.Expression AST节点
	prefixParseFn func() ast.Expression
	// infixParseFn 表达式(运算符)中缀解析函数 - 传入一个 ast.Expression AST节点(表达式(运算符)左侧的内容). 返回一个 ast.Expression AST节点
	infixParseFn func(ast.Expression) ast.Expression
)

// Parser 语法分析器。通过词法分析器，反复前移词法单元，并检查当前的词法单元。以此决定下一步，是该调用其他解析函数，还是直接报错。
type Parser struct {
	lex *lexer.Lexer // 词法分析器指针. 用于获取词法单元

	prevToken token.Token // 上一个词法单元
	curToken  token.Token // 当前词法单元. 当前正在检测的词法单元, 类似于 词法分析器中的position
	peekToken token.Token // 下一个词法单元. 下一个词法单元, 类似于 词法分析器中的readPosition

	errors []string // 语法分析过程中遇见的错误信息

	prefixParseFns map[token.TokenType]prefixParseFn // 词法单元类型 与 表达式(运算符)前缀解析函数 的映射
	infixParseFns  map[token.TokenType]infixParseFn  // 词法单元类型 与 表达式(运算符)中缀解析函数 的映射
}

// New 根据输入的词法分析器，构造一个语法分析器
func New(lex *lexer.Lexer) *Parser {
	parser := &Parser{lex: lex, errors: []string{}}

	// 创建并注册映射表达式解析函数。表达式解析函数在开始解析表达式时，当前curToken必须是所关联的词法单元类型,
	// 返回分析的表达式结果时，curToken是当前表达式类型中的最后一个词法单元。表达式解析函数不会主动推进词法单元
	// 如果有表达式 x == y，则表达式解析时，从 x 开始，到 y 结尾，返回表达式解析结果
	parser.prefixParseFns = make(map[token.TokenType]prefixParseFn)
	// let 变量定义表达式解析函数注册
	parser.registerPrefix(token.IDENT, parser.parseIdentifier)
	// 整数表达式解析函数注册
	parser.registerPrefix(token.INT, parser.parseIntegerLiteral)
	// 前缀表达式解析函数注册 ! - ~
	parser.registerPrefix(token.BANG, parser.parsePrefixExpression)
	parser.registerPrefix(token.MINUS, parser.parsePrefixExpression)
	parser.registerPrefix(token.NOT, parser.parsePrefixExpression)
	// bool表达式解析函数注册
	parser.registerPrefix(token.TRUE, parser.parseBoolean)
	parser.registerPrefix(token.FALSE, parser.parseBoolean)
	// 小括号分组表达式解析函数 - 应该考虑到里面的参数问题
	parser.registerPrefix(token.LPAREN, parser.parseGroupedExpression)
	// if表达式解析函数
	parser.registerPrefix(token.IF, parser.parseIfExpression)
	// 函数表达式解析函数
	parser.registerPrefix(token.FUNCTION, parser.parseFunctionLiteral)
	// 字符串字面量解析函数
	parser.registerPrefix(token.STRING, parser.parseStringLiteral)
	// 数组解析函数
	parser.registerPrefix(token.LBRACKET, parser.parseArrayLiteral)
	// 哈希表解析函数
	parser.registerPrefix(token.LBRACE, parser.parseHashLiteral)
	// 注册中缀表达式解析函数
	parser.infixParseFns = make(map[token.TokenType]infixParseFn)
	parser.registerInfix(token.EQ, parser.parseInfixExpression)
	parser.registerInfix(token.NOT_EQ, parser.parseInfixExpression)
	parser.registerInfix(token.LT, parser.parseInfixExpression)
	parser.registerInfix(token.GT, parser.parseInfixExpression)
	parser.registerInfix(token.PLUS, parser.parseInfixExpression)
	parser.registerInfix(token.MINUS, parser.parseInfixExpression)
	parser.registerInfix(token.SLASH, parser.parseInfixExpression)
	parser.registerInfix(token.ASTERISK, parser.parseInfixExpression)
	// 位运算中缀解析函数
	parser.registerInfix(token.OR, parser.parseInfixExpression)
	parser.registerInfix(token.AND, parser.parseInfixExpression)
	parser.registerInfix(token.XOR, parser.parseInfixExpression)
	parser.registerInfix(token.LSHIFT, parser.parseInfixExpression)
	parser.registerInfix(token.RSHIFT, parser.parseInfixExpression)
	parser.registerInfix(token.URSHIFT, parser.parseInfixExpression)
	// 逻辑运算中缀解析函数
	parser.registerInfix(token.LOGIC_OR, parser.parseInfixExpression)
	parser.registerInfix(token.LOGIC_AND, parser.parseInfixExpression)
	// 调用表达式解析函数 - 在解析的时候，以 ( 作为分割，左边视作将调用的函数，右边除了 ) 外都做为参数。那么可以认为 ( 就是一个中缀运算符，只要为 ( 添加运算符优先级并注册中缀解析函数即可
	//parser.registerInfix(token.LPAREN, parser.parseCallExpression)
	parser.registerInfix(token.LPAREN, parser.parseLParen)
	// 索引运算符表达式解析函数
	parser.registerInfix(token.LBRACKET, parser.parseIndexExpression)
	// 数组索引运算符表达式赋值
	parser.registerInfix(token.ASSIGN, parser.parseIndexAssignExpression)

	// 启动的时候往前推两个，主要是因为语法分析器的curToken是要比词法分析器的position还要后两位的
	// 假设现有: let x = 5; 初始的时候，词法分析器的position是指 l 的，语法分析器的curToken、peekToken
	// 都是为 nil 的，当执行完两次nextToken之后，词法分析器position指向 t，语法分析器的curToken 指向 e peekToken 指向 l
	parser.nextToken()
	parser.nextToken()

	return parser
}

// parseHashLiteral 解析哈希表字面量，因为之前已经做过了 '{' '}' ',' 所以这里只需要多考虑 ':' 即可
func (parser *Parser) parseHashLiteral() ast.Expression {
	exp := &ast.HashLiteral{Token: parser.curToken, Pairs: make(map[ast.Expression]ast.Expression)}

	for !parser.peekTokenIs(token.RBRACE) {
		parser.nextToken()
		key := parser.parseExpression(LOWEST)

		if !parser.expectPeek(token.COLON) {
			return nil
		}
		parser.nextToken()
		val := parser.parseExpression(LOWEST)

		exp.Pairs[key] = val

		if !parser.peekTokenIs(token.RBRACE) && !parser.expectPeek(token.COMMA) {
			return nil
		}
	}

	if !parser.expectPeek(token.RBRACE) {
		return nil
	}

	return exp
}

// parseIndexAssignExpression 解析索引运算符赋值表达式
func (parser *Parser) parseIndexAssignExpression(left ast.Expression) ast.Expression {
	exp := &ast.IndexAssignExpression{Token: parser.curToken, Left: left}

	parser.nextToken()

	exp.Right = parser.parseExpression(LOWEST)

	return exp
}

// parseIndexExpression 解析索引运算符表达式
func (parser *Parser) parseIndexExpression(left ast.Expression) ast.Expression {
	exp := &ast.IndexExpression{Token: parser.curToken, Left: left}

	parser.nextToken()
	exp.Index = parser.parseExpression(LOWEST)

	if !parser.expectPeek(token.RBRACKET) {
		return nil
	}

	return exp
}

// parseExpressionList 解析词法单元列表, 传入一个词法单元类型做为参数，告诉方法以哪个词法单元做为列表的结尾.
func (parser *Parser) parseExpressionList(end token.TokenType) []ast.Expression {
	var list []ast.Expression

	if parser.peekTokenIs(end) {
		parser.nextToken()
		return list
	}

	parser.nextToken()
	list = append(list, parser.parseExpression(LOWEST))

	for parser.peekTokenIs(token.COMMA) {
		parser.nextToken()
		parser.nextToken()
		list = append(list, parser.parseExpression(LOWEST))
	}

	if !parser.expectPeek(end) {
		return nil
	}

	return list
}

// parseTupleLiteral 解析元组字面量
func (parser *Parser) parseTupleLiteral() ast.Expression {
	tup := &ast.TupleLiteral{Token: parser.curToken}
	tup.Elements = parser.parseExpressionList(token.RPAREN)
	return tup
}

// parseArrayLiteral 解析数组字面量
func (parser *Parser) parseArrayLiteral() ast.Expression {
	array := &ast.ArrayLiteral{Token: parser.curToken}
	array.Elements = parser.parseExpressionList(token.RBRACKET)
	return array
}

// parseStringLiteral 解析字符串字面量
func (parser *Parser) parseStringLiteral() ast.Expression {
	return &ast.StringLiteral{Token: parser.curToken, Value: parser.curToken.Literal}
}

// parseIdentifier 解析表达式中的标识符(用户自定义的变量名或函数名、参数名等)
func (parser *Parser) parseIdentifier() ast.Expression {
	return &ast.Identifier{Token: parser.curToken, Value: parser.curToken.Literal}
}

// registerPrefix 注册 词法单元类型 与 表达式(运算符)前缀解析函数 的映射
func (parser *Parser) registerPrefix(tokenType token.TokenType, fn prefixParseFn) {
	parser.prefixParseFns[tokenType] = fn
}

// registerInfix 注册 词法单元类型 与 表达式(运算符)中缀解析函数 的映射
func (parser *Parser) registerInfix(tokenType token.TokenType, fn infixParseFn) {
	parser.infixParseFns[tokenType] = fn
}

// Errors 获取语法分析过程中出现的错误信息
func (parser *Parser) Errors() []string {
	return parser.errors
}

func (parser *Parser) peekError(t token.TokenType) {
	msg := fmt.Sprintf("expected next token tobe %s, but got %s instead. error in %s ", t, parser.peekToken.Type, parser.lex.CurLineInfo())
	parser.errors = append(parser.errors, msg)
}

// NextToken 前移curToken和peekToken
func (parser *Parser) nextToken() {
	parser.prevToken = parser.curToken
	parser.curToken = parser.peekToken
	parser.peekToken = parser.lex.NextToken()
}

// ParserProgram 根据语法分析器构造程序语法树节点
func (parser *Parser) ParserProgram() *ast.Program {
	// 根节点
	program := &ast.Program{}
	program.Statements = []ast.Statement{}

	// 遍历输入的每个词法单元，进行语法解析，遇见EOF则说明读完了, 需要跳出循环
	for !parser.curTokenIs(token.EOF) {
		stmt := parser.parseStatement()
		if stmt != nil {
			program.Statements = append(program.Statements, stmt)
		}
		parser.nextToken()
	}

	return program
}

// parserStatement 解析语句，返回ast.Statement对象
func (parser *Parser) parseStatement() ast.Statement {
	switch parser.curToken.Type {
	case token.LET:
		return parser.parseLetStatement()
	case token.RETURN:
		return parser.parseReturnStatement()
	default:
		return parser.parseExpressionStatement()
	}
}

// parseLetStatement 解析 let 语句，返回ast.LetStatement指针
//
//	使用当前所在的词法单元(token.LET)构造一个LetStatement。然后调用 expectPeek 来判断下一个词法单元
//	是不是一个标识符，如果是，那么词法分析器就往前推进，并构造一个ast.Identifier作为LetStatement的Name字段值。
//	再次调用 expectPeek 来判断下一个词法单元, 是不是赋值符号，接着跳过表达式的处理，返回这个LetStatement
func (parser *Parser) parseLetStatement() *ast.LetStatement {
	defer traceEnd(traceStart("parseLetStatement()"))
	// 构建根节点
	stmt := &ast.LetStatement{Token: parser.curToken}
	// 如果下一个字符不是 用户自定义标识符(函数名、变量名) 直接return nil
	if !parser.expectPeek(token.IDENT) {
		return nil
	}

	stmt.Name = &ast.Identifier{Token: parser.curToken, Value: parser.curToken.Literal}

	if !parser.expectPeek(token.ASSIGN) {
		return nil
	}

	parser.nextToken()

	stmt.Value = parser.parseExpression(LOWEST)

	if fl, ok := stmt.Value.(*ast.FunctionLiteral); ok {
		fl.Name = stmt.Name.Value
	}

	if parser.peekTokenIs(token.SEMICOLON) {
		parser.nextToken()
	}

	return stmt
}

// parseReturnStatement 解析 return 语句 返回 ast.ReturnStatement指针
func (parser *Parser) parseReturnStatement() *ast.ReturnStatement {
	defer traceEnd(traceStart("parseReturnStatement()"))

	stmt := &ast.ReturnStatement{Token: parser.curToken}

	parser.nextToken()

	stmt.ReturnValue = parser.parseExpression(LOWEST)

	if parser.peekTokenIs(token.SEMICOLON) {
		parser.nextToken()
	}

	return stmt
}

// parseExpressionStatement 解析 表达式 返回 ast.ExpressionStatement指针
func (parser *Parser) parseExpressionStatement() *ast.ExpressionStatement {
	defer traceEnd(traceStart("parseExpressionStatement()"))

	stmt := &ast.ExpressionStatement{Token: parser.curToken}

	stmt.Expression = parser.parseExpression(LOWEST)

	if parser.peekTokenIs(token.SEMICOLON) {
		parser.nextToken()
	}

	return stmt
}

// parseBlockStatement 解析 代码块
func (parser *Parser) parseBlockStatement() *ast.BlockStatement {
	defer traceEnd(traceStart("parseBlockStatement()"))

	block := &ast.BlockStatement{Token: parser.curToken}
	block.Statements = []ast.Statement{}

	parser.nextToken()

	for !parser.curTokenIs(token.RBRACE) && !parser.curTokenIs(token.EOF) {
		stmt := parser.parseStatement()
		if stmt != nil {
			block.Statements = append(block.Statements, stmt)
		}
		parser.nextToken()
	}

	return block
}

// parseFunctionParameters 解析函数的参数列表
func (parser *Parser) parseFunctionParameters() []*ast.Identifier {
	defer traceEnd(traceStart("parseFunctionParameters()"))

	identifiers := []*ast.Identifier{}
	// parseFunctionLiteral 中 在调用之前 parseFunctionParameters 先调用了 expectPeek
	// expectPeek 判断为true的情况下，会将curToken往前推一步
	// 所以来到这里的时候 curToken 已经指向 ( 了
	if parser.peekTokenIs(token.RPAREN) {
		parser.nextToken()
		return identifiers
	}

	parser.nextToken()

	ident := &ast.Identifier{Token: parser.curToken, Value: parser.curToken.Literal}
	identifiers = append(identifiers, ident)

	for parser.peekTokenIs(token.COMMA) {
		parser.nextToken()
		parser.nextToken()
		ident := &ast.Identifier{Token: parser.curToken, Value: parser.curToken.Literal}
		identifiers = append(identifiers, ident)
	}

	if !parser.expectPeek(token.RPAREN) {
		return nil
	}

	return identifiers
}

// parseFunctionLiteral 解析函数表达式
func (parser *Parser) parseFunctionLiteral() ast.Expression {
	defer traceEnd(traceStart("parseFunctionLiteral()"))

	lit := &ast.FunctionLiteral{Token: parser.curToken}

	if !parser.expectPeek(token.LPAREN) {
		return nil
	}

	lit.Parameters = parser.parseFunctionParameters()

	if !parser.expectPeek(token.LBRACE) {
		return nil
	}

	lit.Body = parser.parseBlockStatement()

	return lit
}

// parseIfExpression 解析 if 表达式
func (parser *Parser) parseIfExpression() ast.Expression {
	defer traceEnd(traceStart("parseIfExpression()"))

	expression := &ast.IFExpression{Token: parser.curToken}

	if !parser.expectPeek(token.LPAREN) {
		return nil
	}

	parser.nextToken()
	expression.Condition = parser.parseExpression(LOWEST)

	if !parser.expectPeek(token.RPAREN) {
		return nil
	}

	if !parser.expectPeek(token.LBRACE) {
		return nil
	}

	expression.Consequence = parser.parseBlockStatement()

	// 到这里的时候 curToken 是在 } 处的
	if parser.peekTokenIs(token.ELSE) {
		// 所以这里要先往前推进一步，推到 else 处
		parser.nextToken()
		// 接着我们期望下一个词法单元应该是一个 {
		if !parser.expectPeek(token.LBRACE) {
			return nil
		}

		expression.Alternative = parser.parseBlockStatement()
	}

	return expression
}

// parseGroupedExpression 解析小括号分组表达式.
func (parser *Parser) parseGroupedExpression() ast.Expression {
	defer traceEnd(traceStart("parseGroupedExpression()"))
	// 直接往前面解析直到碰见 )
	parser.nextToken()

	exp := parser.parseExpression(LOWEST)

	// 如果第一个元素后面跟的是 ',' 那么这个 '(' 表达式就是一个元组
	if parser.peekTokenIs(token.COMMA) {
		parser.nextToken()

		tup := &ast.TupleLiteral{Token: parser.curToken}
		tup.Elements = parser.parseExpressionList(token.RPAREN)
		tup.Elements = append([]ast.Expression{exp}, tup.Elements...)

		return tup
	}

	if !parser.expectPeek(token.RPAREN) {
		return nil
	}

	return exp
}

// parseBoolean 解析bool表达式
func (parser *Parser) parseBoolean() ast.Expression {
	defer traceEnd(traceStart("parseBoolean()"))

	stmt := &ast.Boolean{Token: parser.curToken}
	value, err := strconv.ParseBool(parser.curToken.Literal)
	if err != nil {
		msg := fmt.Sprintf("could not parse %q as bool. err in %s", parser.curToken.Literal, parser.lex.CurLineInfo())
		parser.errors = append(parser.errors, msg)
		return nil
	}
	stmt.Value = value
	return stmt
}

// parseIntegerLiteral 解析整数字面量表达式
func (parser *Parser) parseIntegerLiteral() ast.Expression {
	defer traceEnd(traceStart("parseIntegerLiteral()"))

	stmt := &ast.IntegerLiteral{Token: parser.curToken}
	value, err := strconv.ParseInt(parser.curToken.Literal, 0, 64)
	if err != nil {
		msg := fmt.Sprintf("could not parse %q as integer. err in %s", parser.curToken.Literal, parser.lex.CurLineInfo())
		parser.errors = append(parser.errors, msg)
		return nil
	}
	stmt.Value = value
	return stmt
}

// parseExpression 通过parser的映射函数解析表达式. precedence表示当前调用中的右约束能力，右约束能力越强，右边
//
//	所能包含的词法单元就越多，比如：当前词法单元为 ( 时，和当前词法单元为 + 时，明显 ( 需要考虑的东西要多得多
//	那么相对的，parser.peekPrecedence() 表示的就是 左约束能力，不过它代表的是下一个词法单元的左约束能力，
//	如果当前词法单元的右约束能力 小于 下一个词法单元的左约束能力，那么当前词法单元就应当与下一个词法单元融合，
//	然后传递给下一个词法单元的infixParseFn进行进一步的解析
func (parser *Parser) parseExpression(precedence int) ast.Expression {
	defer traceEnd(traceStart(fmt.Sprintf("parseExpression(%d)", precedence)))

	prefix := parser.prefixParseFns[parser.curToken.Type]
	if prefix == nil {
		parser.noPrefixParseFnError(parser.curToken.Type)
		return nil
	}
	leftExp := prefix()

	for !parser.peekTokenIs(token.SEMICOLON) && precedence < parser.peekPrecedence() {
		infix := parser.infixParseFns[parser.peekToken.Type]
		if infix == nil {
			return leftExp
		}

		parser.nextToken()

		leftExp = infix(leftExp)
	}

	return leftExp
}

// parsePrefixExpression 解析前缀表达式
func (parser *Parser) parsePrefixExpression() ast.Expression {
	defer traceEnd(traceStart("parsePrefixExpression()"))

	expression := &ast.PrefixExpression{
		Token:    parser.curToken,
		Operator: parser.curToken.Literal,
	}
	parser.nextToken()

	expression.Right = parser.parseExpression(PREFIX)

	return expression
}

// parseLParen 解析 '(' 符号. 根据'(' 的上一个词法单元是什么词法单元来判断这个 '(' 是方法还是元组
func (parser *Parser) parseLParen(exp ast.Expression) ast.Expression {
	// '(' 的上一个词法单元是赋值符号，那么判定它是一个元组
	// 考虑的更细致些，比如箭头函数这种，可能还要需要结合下一个词法单元的类型一起来判断
	if parser.prevToken.Type == token.ASSIGN {
		return parser.parseTupleLiteral()
	}
	// 默认认为是准备进行函数调用
	return parser.parseCallExpression(exp)

	//switch parser.prevToken.Type {
	//case token.FUNCTION, token.IDENT:
	//	return parser.parseCallExpression(exp)
	//case token.ASSIGN:
	//	return parser.parseTupleLiteral()
	//default:
	//	return exp
}

// parseCallExpression 解析调用表达式，将 ( 视作中缀，左边做为 function 右边做为 arguments
func (parser *Parser) parseCallExpression(function ast.Expression) ast.Expression {
	exp := &ast.CallExpression{Token: parser.curToken, Function: function}
	exp.Arguments = parser.parseExpressionList(token.RPAREN)
	return exp
}

// parseInfixExpression 解析中缀表达式
func (parser *Parser) parseInfixExpression(left ast.Expression) ast.Expression {
	defer traceEnd(traceStart(fmt.Sprintf("parseInfixExpression(%v)", left)))

	exp := &ast.InfixExpression{
		Token:    parser.curToken,
		Operator: parser.curToken.Literal,
		Left:     left,
	}
	precedence := parser.curPrecedence()
	parser.nextToken()

	// 降低 + 优先级以实现 + 右关联
	//if exp.Operator == "+" {
	//	exp.Right = parser.parseExpression(precedence - 1)
	//} else {
	exp.Right = parser.parseExpression(precedence)
	//}

	return exp
}

// noPrefixParseFnError 没有处理前缀表达式的方法
func (parser *Parser) noPrefixParseFnError(t token.TokenType) {
	msg := fmt.Sprintf("no prefix parse function for %s found. error in %s ", t, parser.lex.CurLineInfo())
	parser.errors = append(parser.errors, msg)
}

// expectPeek 判断下一次词法单元是不是指定的类型，如果是，那么就往前推进一步curToken、peekToken，然后返回true，否则直接返回false
func (parser *Parser) expectPeek(tokenType token.TokenType) bool {
	if parser.peekTokenIs(tokenType) {
		parser.nextToken()
		return true
	}
	parser.peekError(tokenType)
	return false
}

// peekTokenIs 传入一个 token.TokenType 判断语法分析器下一个要分析的词法单元是否为这种词法单元类型
func (parser *Parser) peekTokenIs(tokenType token.TokenType) bool {
	return parser.peekToken.Type == tokenType
}

// curTokenIs 传入一个 token.TokenType 判断语法分析器当前分析的词法单元是否为这种词法单元类型
func (parser *Parser) curTokenIs(tokenType token.TokenType) bool {
	return parser.curToken.Type == tokenType
}

// peekPrecedence 获取 peekToken 的优先级
func (parser *Parser) peekPrecedence() int {
	if p, ok := precedences[parser.peekToken.Type]; ok {
		return p
	}
	return LOWEST
}

// curPrecedence 获取 curToken 的优先级
func (parser *Parser) curPrecedence() int {
	if p, ok := precedences[parser.curToken.Type]; ok {
		return p
	}
	return LOWEST
}
